<?
// *****************************************************************************
// Модуль Subversion
// Префикс svn_
// Автор: Алексей Дьяченко
// Библиотека распространяется по лицензии GPL
// Принять участие в разработке или скачать новую версию вы можете на сайте
// http://www.my-site.ru/
// *****************************************************************************



echo '<pre>';
$svn = new svnlib_svn();
$svn->set_repository('http://my-site-framework.googlecode.com/svn/trunk/',
null,null,
array('non-interactive'));
print_r($svn->get_log('htdocs/index.php'));
echo $svn->get_file('htdocs/index.php');
print_r($svn->get_filediff('htdocs/index.php','3:27'));
echo '</pre>';
/**
 * Работа с репозитарием subversion
 * @author
 */
class svnlib_svn
{
	private $url = '';
	private $login = null;
	private $password = null;
	private $option_global = array();
	private $svn = '/usr/bin/svn';
	//
	function set_repository($url,$login=null,$password=null,$option_global=null)
	{
		//
		$this->url = $url;
		$this->login = $login;
		$this->password = $password;
		$this->global_option = $option_global;
	}
	
	/**
	 * Обращение к системе контроля версий через командную строку	
	 * @param $cmdline
	 * @param $addpath
	 * @return mixed boolean or array
	 */
	private function svnexec($cmdline,$addpath='')
	{
		//
		// Производим автозамену в коммандной строке
		$cmdline=str_replace("{rep_url}",$this->url,$cmdline);
		$cmdline=str_replace("{rep_addpath}",$addpath,$cmdline);
		$cmdline=str_replace("{rep_fullpath}",$this->url.$addpath,$cmdline);
		
		$svncmd = "{$this->svn} {$cmdline}";
		set_time_limit(0);
		// Выполняем команду
		exec($svncmd,$output,$status);
		// Проверяем результат
		if($status!==0)
		{
			mst_error('Ошибка обращения к репозитарию',
				"Вызов {$svncmd} завершился неудачно",2);
			return false;
		}
		return $output;
	}
	/**
	 * Исполняет команду в SVN и возвращает результат	
	 * @param $cmd
	 * @param $options_add
	 * @param $xml
	 * @return mixed
	 */
	private function do_cmd($cmd,$path='',$options_add,$resformat='text')
	{
		
		// *************************
		// Добавляем специальные опции
		if (!is_null($this->login))
		{
			//
			$options_add['username'] = $this->login;
		}
		if (!is_null($this->password))
		{
			//
			$options_add['username'] = $this->password;
		}
		if ($resformat==='xml')
		{
			//
			$options_add['xml'] = '';
		}
		
		// Складываем массивы с опциями
		// Совпадающие опции преобладают из массива $option_add
		// Преобразуем в строку
		$options = $this->options2str($options_add + $this->option_global);
		
		// Выполняем запрос к svn
		$svn_cmd = "{$cmd} {$options} {rep_fullpath}";
		
		// Исполняем команду
		if (!is_array($output=$this->svnexec($svn_cmd,$path)))
		{
			// Команда завершилась неудачно
			mst_error('Ошибка обращения к репозитарию',
				"Результат, возвращенный командой {$svn_cmd} не является массивом",1);
			// print_r($output);
			return false;
		}
		
		// Преобразуем результат
		switch($resformat)
		{
			case 'xml':
				return simplexml_load_string(implode('',$output));
			break;
			case 'text':
				return implode("\n",$output);
			break;
			case 'array':
			default:
				return $output;
			break;
		} 
		return $output;
	}
	
	/**
	 * Преобразовать массив с опциями в строку	
	 * @param $options_array
	 * @return string
	 */
	private function options2str($options_array)
	{
		//
		$options_text = '';
		foreach ($options_array as $key=>$value)
		{
			$options_text .= "--{$key} {$value} ";
		}
		return $options_text;
	}
	
	/** 
	 * Запросить историю изменений из CVS	
	 * @param $path
	 * @return mixed string or simplemxml_element or boolean or array
	 */
	function get_log($path='')
	{
		$options_add = array();
		$options_add['verbose'] = '';
		return $vcsres = $this->do_cmd('log',$path,$options_add,'xml');
	}
	
	/**
	 * Запросить текстовый файл из CVS	
	 * @param $path
	 * @return mixed string or simplemxml_element or boolean or array
	 */
	function get_file($path='',$revison=null)
	{
		//
		$options_add = array();
		if(!is_null($revison))
		{
			// Устанавливаем извлекаемую ривизию
			$options_add['revision']=$revison;
		}
		// $options_add['verbose'] = '';
		return $vcsres = $this->do_cmd('cat',$path,$options_add,'text');
	}
	
	function get_filediff($path='',$revison=null)
	{
		//
		$options_add = array();
		if(!is_null($revison))
		{
			// Устанавливаем сравниваемые ревизии
			$options_add['revision']=$revison;
		}
		// $options_add['verbose'] = '';
		return $vcsres = $this->do_cmd('diff',$path,$options_add,'array');
	}
}
?>
